﻿#VisualFreeBasic_Form#  Version=5.9.6
Locked=0

[Form]
Name=Form1
Help=False
ClassStyle=CS_VREDRAW,CS_HREDRAW,CS_DBLCLKS
ClassName=
WinStyle=WS_THICKFRAME,WS_CAPTION,WS_SYSMENU,WS_CLIPSIBLINGS,WS_CLIPCHILDREN,WS_VISIBLE,WS_EX_WINDOWEDGE,WS_EX_CONTROLPARENT,WS_EX_LEFT,WS_EX_LTRREADING,WS_EX_RIGHTSCROLLBAR,WS_EX_TOPMOST,WS_POPUP,WS_SIZEBOX
Style=3 - 常规窗口
Icon=
Caption=简易录屏辅助（按下Ctrl 用鼠标在屏幕中画，放开清屏恢复）
StartPosition=1 - 屏幕中心
WindowState=0 - 正常
Enabled=True
Repeat=False
Left=0
Top=0
Width=643
Height=450
TopMost=True
Child=False
MdiChild=False
TitleBar=True
SizeBox=True
SysMenu=True
MaximizeBox=False
MinimizeBox=False
Help=False
Hscroll=False
Vscroll=False
MinWidth=500
MinHeight=300
MaxWidth=0
MaxHeight=0
NoActivate=False
MousePass=False
TransPer=-1
TransColor=RGB(255,0,255)
Shadow=4 - 大阴影
BackColor=RGB(0,0,204)
MousePointer=0 - 默认
Tag=
Tab=True
ToolTip=
ToolTipBalloon=False
AcceptFiles=False

[Timer]
Name=Timer1
Help=
Index=-1
Interval=1
Enabled=True
Left=350
Top=475
Tag=

[WinHook]
Name=WinHook1
Help=
Left=145
Top=475
Tag=

[MyDrawWin]
Name=MyDrawWin1
Help=
Enabled=True
Caption=
ButtonTop=False
ButtonMax=True
ButtonMin=True
ButtonClose=True
ButtonSkin=False
ButtonMenu=False
BorderTitle=24
BorderLR=3
BorderB=3
BorderColor=RGB(0,77,77)
BorderColor2=RGB(0,77,77)
Fillet=10
Left=35
Top=480
Tag=

[Picture]
Name=Picture1
Help=
Index=-1
Style=0 - 无边框
Enabled=True
Visible=True
Left=5
Top=12
Width=620
Height=395
Layout=0 - 不锚定
MousePointer=0 - 默认
Tag=
Tab=True
ToolTip=
ToolTipBalloon=False
AcceptFiles=False

[PopupMenu]
Name=PopupMenu1
Help=
Index=-1
Menu=红色Form1_PopupMenu1_Menu10-10橙色Form1_PopupMenu1_Menu20-10黄色Form1_PopupMenu1_Menu30-10绿色Form1_PopupMenu1_Menu40-10蓝色Form1_PopupMenu1_Menu50-10紫色Form1_PopupMenu1_Menu60-10黑色Form1_PopupMenu1_Menu70-10白色Form1_PopupMenu1_Menu80-10
Left=240
Top=485
Tag=


[AllCode]
Type 鼠标按键类
   x As Long 
   y As Long 
   按键 As Long 'WM_LBUTTONDOWN  WM_MBUTTONDOWN  WM_RBUTTONDOWN WM_MOUSEWHEEL
   时间 As ULong 
   
End Type 
Dim Shared 开始画画 As Long, dc底图 As HDC, bm底图 As HBITMAP  ,颜色 As ULong ,a鼠标按键(30) As 鼠标按键类

'[Form1.Picture1]事件 : 重绘，系统通知控件需要重新绘画。
'hWndForm    当前窗口的句柄(WIN系统用来识别窗口的一个编号，如果多开本窗口，必须 Me.hWndForm = hWndForm 后才可以执行后续操作本窗口的代码)
'hWndControl 当前控件的句柄(也是窗口句柄，如果多开本窗口，必须 Me.控件名.hWndForm = hWndForm 后才可以执行后续操作本控件的代码 )
Function Form1_Picture1_WM_Paint(hWndForm As hWnd, hWndControl As hWnd) As LResult
   Dim gg As yGDI = yGDI(hWndControl, BGR(255, 0, 255), True) 'WM_PAINT事件里必须用这行初始化 yGDI
   '若不用 yGDI 也可以直接使用API，必须使用 BeginPaint 初始化才能画，然后返回 TRUE，没有这样绘画的必须返回零。
   'Dim ps  As PAINTSTRUCT
   'Dim nDC As HDC = BeginPaint(hWndControl, @ps) '初始化并获取DC
   'EndPaint(hWndControl, @ps) '结束绘画
   If dc底图 = 0 Then
      dc底图 = CreateCompatibleDC(0)
      Dim m_Bmp As HBITMAP
      m_Bmp = CreateCompatibleBitmap(gg.m_Dc, gg.m_Width, gg.m_Height)
      DeleteObject SelectObject(dc底图, m_Bmp) ' 将位图选择到兼容的设备上下文中
      SetStretchBltMode dc底图, HALFTONE 'COLORONCOLOR
      DrawFrame dc底图, 0, 0, gg.m_Width, gg.m_Height, BGR(255, 0, 255)
   End If
   BitBlt gg.m_Dc, 0, 0, gg.m_Width, gg.m_Height, dc底图, 0, 0, SRCCOPY '将原内容获取到内存DC
   gg.Brush -1
   Dim i As Long, cc As Long, t As Long, ts As ULong = GetTickCount, mm As WString * 10  ,x As Long ,y As Long,w As Long =DpiUnScaleI(gg.m_Width )
   gg.Font ,12
   For i = 0 To 30
      If a鼠标按键(i).按键 Then
         Select Case a鼠标按键(i).按键
            Case WM_LBUTTONDOWN
               cc = &H0
               mm = WStr("鼠标左键点击")
            Case WM_MBUTTONDOWN
               cc = &HFF33FF
               mm = WStr("鼠标中键点击")
            Case WM_RBUTTONDOWN
               cc = &H8C1AFF
               mm = WStr("鼠标右键点击")
            Case WM_MOUSEWHEEL
               cc = &HFFFF
               mm = WStr("鼠标上下滚轮")
         End Select
         t = (ts - a鼠标按键(i).时间) / 10
         If t < 5 Then t = 5
         gg.Pen 1, cc
         
         If a鼠标按键(i).按键 = WM_MOUSEWHEEL Then
            gg.DrawCircleFrame a鼠标按键(i).x - 5, a鼠标按键(i).y - t / 2, 10, t, 5, 5
            gg.SetColor &H0, cc
            x= a鼠标按键(i).x+5  :y=  a鼠标按键(i).y -40
            
         Else
            gg.SetColor &HFFFFFF, cc
            gg.DrawEllipse a鼠标按键(i).x - t / 2, a鼠标按键(i).y - t / 2, t, t
            x=a鼠标按键(i).x+5 :y= a鼠标按键(i).y -40
         End If
         If y < 0 Then y = 0
         If x < 0 Then x = 0
         If x+100>w Then x=w-100
          gg.DrawString x, y, mm
      End If
   Next
   
   Function = TRUE ' 告诉系统，我们自绘了（yGDI必须WM_PAINT初始化，若API必须用BeginPaint初始化），不需要系统绘画。
End Function
'[Form1]事件 : 完成创建窗口及所有的控件后，此时窗口还未显示。注：自定义消息里 WM_Create 此时还未创建控件和初始赋值。
'hWndForm  当前窗口的句柄(WIN系统用来识别窗口的一个编号，如果多开本窗口，必须 Me.hWndForm = hWndForm 后才可以执行后续操作本窗口的代码)
'UserData  来自显示窗口最后1个参数，例： Form2.Show(父窗口句柄,模式,UserData)
Sub Form1_WM_Create(hWndForm As hWnd, UserData As Integer)
   Me.WindowPlacementLoad App.Path & "配置.ini", "Form1" '恢复窗口位置和大小
   颜色 = ValInt(INI_GetKey(App.Path & "配置.ini", "setup", "colour", WStr(BGR(255, 0, 0)))) 'GDI的颜色值。
   Form2.Show(hWndForm)
   Dim As Rect rc
   GetWindowRect(Picture1.hWnd, @rc)
   Form2.Move rc.Left, rc.top, rc.Right - rc.Left, rc.bottom - rc.top
   Form3.Show(hWndForm)
   GetWindowRect(hWndForm, @rc)
   Form3.Move rc.Right - rc.Left - AfxScaleX(250) + rc.Left, rc.top + AfxScaleY(4), AfxScaleY(200), AfxScaleY(20)
   Form3.YFbunGroup1.ButtonMark(Form3_YFbunGroup1_Button_1) = 颜色
End Sub
'[Form1]事件 : 窗口完全显示后。
'hWndForm  当前窗口的句柄(WIN系统用来识别窗口的一个编号，如果多开本窗口，必须 Me.hWndForm = hWndForm 后才可以执行后续操作本窗口的代码)
'UserData  来自显示窗口最后1个参数，例： Form2.Show(父窗口句柄,模式,UserData)
Sub Form1_Shown(hWndForm As hWnd, UserData As Integer)
   
End Sub

'[Form1]事件 : 窗口已经改变了大小
'hWndForm  当前窗口的句柄(WIN系统用来识别窗口的一个编号，如果多开本窗口，必须 Me.hWndForm = hWndForm 后才可以执行后续操作本窗口的代码)
'fwSizeType = SIZE_MAXHIDE     SIZE_MAXIMIZED   SIZE_MAXSHOW    SIZE_MINIMIZED    SIZE_RESTORED
''            其他窗口最大化   窗口已最大化     其他窗口恢复    窗口已最小化      窗口已调整大小
'nWidth nHeight  是客户区大小，不是全部窗口大小。
Sub Form1_WM_Size(hWndForm As hWnd, fwSizeType As Long, nWidth As Long, nHeight As Long)
   if fwSizeType = SIZE_MINIMIZED Then Return
   'xxx.Move AfxScaleX(5), AfxScaleY(5), nWidth - AfxScaleX(10), nHeight - AfxScaleY(30)
   If dc底图 Then DeleteDC dc底图
   Picture1.Move(AfxScaleX(2), AfxScaleY(2), nWidth - AfxScaleX(4), nHeight - AfxScaleY(4))
   Dim As Rect rc
   GetWindowRect(Picture1.hWnd, @rc)
   Form2.Move rc.Left, rc.top, rc.Right - rc.Left, rc.bottom - rc.top
   GetWindowRect(hWndForm, @rc)
   Form3.Move rc.Right - rc.Left - AfxScaleX(250) + rc.Left, rc.top + AfxScaleY(4), AfxScaleY(200), AfxScaleY(20)
   'Picture1.Refresh
End Sub

'[Form1]事件 : 自定义消息（全部消息），在其它事件处理后才轮到本事件。
'hWndForm    当前窗口的句柄(WIN系统用来识别窗口的一个编号，如果多开本窗口，必须 Me.hWndForm = hWndForm 后才可以执行后续操作本窗口的代码)
'wMsg        消息值，0--&H400 由WIN系统定义，用户自定义是 WM_USER+** 定义。例 PostMessage( 窗口句柄 , Msg , wParam , lParam )
'wParam      主消息参数，什么作用，由发送消息者定义
'lParam      副消息参数，什么作用，由发送消息者定义
Function Form1_Custom(hWndForm As hWnd, wMsg As UInteger, wParam As wParam, lParam As lParam) As LResult
   Select Case wMsg
      Case WM_MOVE
         Dim As Rect rc
         GetWindowRect(Picture1.hWnd, @rc)
         Form2.Move rc.Left, rc.top, rc.Right - rc.Left, rc.bottom - rc.top
         GetWindowRect(hWndForm, @rc)
         Form3.Move rc.Right - rc.Left - AfxScaleX(250) + rc.Left, rc.top + AfxScaleY(4), AfxScaleY(200), AfxScaleY(20)
   End Select
   Function = FALSE ' 若不想系统继续处理此消息，则应返回 TRUE （俗称吃掉消息）。
   
End Function

'[Form1.WinHook1]事件 : 底层键盘钩子(全系统有效)
'每当新的键盘输入事件即将发布到线程输入队列中时，系统都会调用此函数。
'nCode   挂钩过程用来确定如何处理消息的代码。如果nCode小于零，必须向下传递。nCode=HC_ACTION  按键消息
'KeyMsg  键盘消息的标识符。此参数是以下消息之一：WM_KEYDOWN WM_KEYUP WM_SYSKEYDOWN WM_SYSKEYUP
'lKey    lKey.vkCode   虚拟键代码。详细看微软的 https://docs.microsoft.com/zh-cn/windows/win32/inputdev/virtual-key-codes
''       lKey.scanCode 硬件扫描代码。
''       lKey.flags    扩展标志 = (lKey.flags And 1)  : 指示该键是否为扩展键，例如出现在增强型101键或102键键盘上的右侧ALT和CTRL键。如果是扩展键，则值为1；否则为0
''                     完整级别 = (lKey.flags And 2)  : 是否从较低完整性级别运行的进程注入事件。如果是这种情况，则该值为2；否则为0
''                     注入事件 = (lKey.flags And 16) : 是否注入事件。如果是这种情况，则该值为16；否则为0。
''                     上下文   = (lKey.flags And 32) : 如果ALT键按下，则值为32；否则，值为0。
''                     过渡状态 = (lKey.flags And 64) : 如果按下键，则值为0；如果释放键，则值为64。
Function Form1_WinHook1_LowLevelKeyboardProc(ByVal nCode As Integer, ByVal KeyMsg As UInteger, ByRef lKey As KBDLLHOOKSTRUCT) As LResult
   if nCode = HC_ACTION Then '=HC_ACTION 才是用户处理
      '这里是用户代码， 如果想屏蔽（俗称吃掉）这消息，则最后写：Return TRUE
      If KeyMsg = 256 Then
         If 开始画画 = 0 Then
            If dc底图 Then DeleteDC dc底图
            dc底图 = 0
            Picture1.Refresh
            开始画画        = 1
            Form2.MousePass = False
         End If
      elseif KeyMsg = 257 then
         开始画画 = 0
         If dc底图 Then DeleteDC dc底图
         dc底图 = 0
         Picture1.Refresh
         Form2.MousePass = True
      End If
      'Print KeyMsg, lKey.vkCode ,lKey.FLAGS
      
   End If
   Function = CallNextHookEx(0, nCode, KeyMsg, Cast(lParam, @lKey)) '传递到下一个挂钩过程。
End Function

'[Form1]事件 : 即将关闭窗口，返回非0可阻止关闭
'hWndForm  当前窗口的句柄(WIN系统用来识别窗口的一个编号，如果多开本窗口，必须 Me.hWndForm = hWndForm 后才可以执行后续操作本窗口的代码)
Function Form1_WM_Close(hWndForm As hWnd) As LResult
   Me.WindowPlacementSave App.Path & "配置.ini", "Form1" '保存窗口位置和大小
   
   Function = False ' 返回 TRUE 阻止关闭窗口。
End Function

'[Form1.PopupMenu1]事件 : 点击了菜单项
'hWndForm 当前窗口的句柄(WIN系统用来识别窗口的一个编号，如果多开本窗口，必须 Me.hWndForm = hWndForm 后才可以执行后续操作本窗口的代码)
''           本控件为功能控件，就是无窗口，无显示，只有功能。如果多开本窗口，必须 Me.控件名.hWndForm = hWndForm 后才可以执行后续操作本控件的代码
'wID      菜单项命令ID
Sub Form1_PopupMenu1_WM_Command(hWndForm As hWnd, wID As ULong)
   
   Select Case wID
      Case Form1_PopupMenu1_Menu1 ' 红色
         颜色 = BGR(254, 0, 0) 'GDI的颜色值。
      Case Form1_PopupMenu1_Menu2 ' 橙色
         颜色 = BGR(255, 102, 0) 'GDI的颜色值。
      Case Form1_PopupMenu1_Menu3 ' 黄色
         颜色 = BGR(255, 229, 26) 'GDI的颜色值。
      Case Form1_PopupMenu1_Menu4 ' 绿色
         颜色 = BGR(0, 255, 1) 'GDI的颜色值。
      Case Form1_PopupMenu1_Menu5 ' 蓝色
         颜色 = BGR(1, 102, 255) 'GDI的颜色值。
      Case Form1_PopupMenu1_Menu6 ' 紫色
         颜色 = BGR(163, 41, 204) 'GDI的颜色值。
      Case Form1_PopupMenu1_Menu7 ' 黑色
         颜色 = BGR(0, 0, 0) 'GDI的颜色值。
      Case Form1_PopupMenu1_Menu8 ' 白色
         颜色 = BGR(255, 255, 255) 'GDI的颜色值。
   End Select
   INI_SetKey(App.Path & "配置.ini", "setup", "colour", WStr(颜色)) 'GDI的颜色值。
   Form3.YFbunGroup1.ButtonMark(Form3_YFbunGroup1_Button_1) = 颜色
   
End Sub

'[Form1.WinHook1]事件 : 底层鼠标钩子(全系统有效)
'每当新的鼠标输入事件即将发布到线程输入队列中时，系统都会调用此函数。
'nCode     挂钩过程用来确定如何处理消息的代码。如果nCode小于零，必须向下传递。nCode=HC_ACTION  鼠标消息
'MouseMsg  鼠标消息标识符。此参数是以下消息之一（未全面）： WM_LBUTTONDOWN WM_LBUTTONUP WM_MOUSEMOVE WM_MOUSEWHEEL WM_MOUSEHWHEEL WM_RBUTTONDOWN WM_RBUTTONUP
'lMouse    鼠标事件信息，lMouse.pt.x 和 lMouse.pt.y ，光标的x坐标和y坐标，以每个监视器可见的屏幕坐标表示。
''                       lMouse.mouseData  如果消息为 WM_MOUSEWHEEL，则 鼠标滚轮值 WheelDelta=GET_Y_LPARAM(lMouse.mouseData)
''                                         如果消息是 WM_XBUTTONDOWN WM_XBUTTONUP WM_XBUTTONDBLCLK WM_NCXBUTTONDOWN WM_NCXBUTTONUP WM_NCXBUTTONDBLCLK 则 X按钮=GET_Y_LPARAM(lMouse.mouseData) :是1或2按下 (X按钮 And XBUTTON1)<>0 :  (X按钮 And XBUTTON2)<>0
''                       lMouse.flags      事件注入标志，事件注入 = (lMouse.flags And 1) ，完整级别 =(lMouse.flags And 2)
''                       lMouse.time       此消息的时间戳。
''                       lMouse.dwExtraInfo 与消息关联的其他信息。。
Function Form1_WinHook1_LowLevelMouseProc(ByVal nCode As Integer, ByVal MouseMsg As UInteger, ByRef lMouse As MSLLHOOKSTRUCT) As LResult
   if nCode = HC_ACTION Then '=HC_ACTION 才是用户处理
      '这里是用户代码， 如果想屏蔽（俗称吃掉）这消息，则最后写：Return TRUE
      If 开始画画 = 0 Then
         If MouseMsg = WM_LBUTTONDOWN Or MouseMsg = WM_MBUTTONDOWN Or MouseMsg = WM_RBUTTONDOWN Or MouseMsg = WM_MOUSEWHEEL Then
            Dim i As Long
            For i = 0 To 30
               If a鼠标按键(i).按键 = 0 Then
                  Dim As Rect rc
                  GetWindowRect(Form1.Picture1.hWnd, @rc)
                  If lMouse.pt.x < rc.Left Or lMouse.pt.y < rc.top Or lMouse.pt.x > rc.Right Or lMouse.pt.y > rc.bottom Then Exit For 
                  a鼠标按键(i).x    = DpiUnScaleI(lMouse.pt.x - rc.Left)
                  a鼠标按键(i).y    = DpiUnScaleI(lMouse.pt.y - rc.top)
                  a鼠标按键(i).按键 = MouseMsg
                  a鼠标按键(i).时间 = GetTickCount
                  Exit For
               End If
            Next
         End If
      End If
   End If
   Function = CallNextHookEx(0, nCode, MouseMsg, Cast(lParam, @lMouse)) '传递到下一个挂钩过程。
End Function

'[Form1.Timer1]事件 : 定时器
'hWndForm  当前窗口的句柄(WIN系统用来识别窗口的一个编号，如果多开本窗口，必须 Me.hWndForm = hWndForm 后才可以执行后续操作本窗口的代码)
''         本控件为功能控件，就是无窗口，无显示，只有功能。如果多开本窗口，必须 Me.控件名.hWndForm = hWndForm 后才可以执行后续操作本控件的代码
'wTimerID  定时器ID，区分不同定时器的编号
Sub Form1_Timer1_WM_Timer(hWndForm As hWnd, wTimerID As Long)
   Dim i As Long, j As Long, t As ULong = GetTickCount
   For i = 0 To 30
      If a鼠标按键(i).按键 Then
         If t - a鼠标按键(i).时间 > 800 Then
            a鼠标按键(i).按键 = 0
         End If
         j += 1
      End If
   Next
   If j Then Picture1.Refresh
End Sub















